package cn.tedu.justone.pack02;

/**
 * ZZ：JustOne
 * VX：Andylau2020smile
 * DY：JustOne2018
 * ZT：《演示wait(), notify(), notifyAll()》
 */
public class Demo11_方法示例wait_notify_notifyAll {

    //演示 wait(), notify(), notifyAll()
    //演示 wait(), notify(), notifyAll()
    //演示 wait(), notify(), notifyAll()

    //基本用法：
    //1,lock.wait()的作用是让当前线程进入等待状态并释放它持有的锁对象。
    //  直到其他线程调用lock.notify()或 lock.notifyAll()，当前线程被唤醒进入就绪状态
    //2,lock.notify()的作用是唤醒lock锁对象的等待队伍中随机的一个线程
    //3,lock.notifyAll()的作用是唤醒lock锁对象等待队伍中的所有线程

    //注意事项：
    //1,wait、notify、notifyAll只能在synchronized中用锁对象调用，
    //  否则会产生IllegalMonitorStateException。
    //2,主叫方 和 被叫方 各自的同步块必须持有同一个锁对象、且由同一个锁对象调用。
    //3,唤醒机制更倾向于notifyAll，而不是notify。

    //------------------------------------------------------------

    //本例思路：
    // 创建三条线程并让他们执行lock.wait(),
    // 然后在主线程中执行notify() 和 notifyAll()进行测试

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        t1.start();
        t2.start();
        t3.start();
        Thread t4 = new Thread(){
            @Override
            public void run() {
                synchronized (MyThread.LOCK){
                    System.out.println(Thread.currentThread().getName() + " 执行了 notify()");
                    MyThread.LOCK.notify();//只能唤醒一个  不会释放锁
                    //MyThread.LOCK.notifyAll();//可以唤醒所有
                    System.out.println("我叫醒了一个人");
                    try {
                        Thread.sleep(7000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }
        };

        t4.start();
        //休眠的目的上让受检的三条线程先进入wait()
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //尝试执行notify(), notifyAll()
        //要求主叫方 和 被叫方 必须持有同一个锁对象
        //synchronized (MyThread.LOCK){
        //    System.out.println(Thread.currentThread().getName() + " 执行了 notify()");
        //    MyThread.LOCK.notify();//只能唤醒一个
        //    //MyThread.LOCK.notifyAll();//可以唤醒所有
        //}

    }
}

class MyThread extends Thread{
    public static String LOCK = "刘景景";
    @Override
    public void run() {

        synchronized (LOCK){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                System.out.println(Thread.currentThread().getName() + "执行了wait()"+ System.currentTimeMillis());
                LOCK.wait(); // 会释放锁
                System.out.println(Thread.currentThread().getName() + " 被唤醒并运行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}























